#pragma once
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string>
#include <iostream>
using namespace std;

// 目标：利用共享内存，实现service和client的通信

#define SIZE 4096
#define gmode 0666
#define EXIT(m)             \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    }

class Shm
{
public:
    Shm(string &pathname, int &projid)
    {
        _key = ftok(pathname.c_str(), projid);
    }

    // 创建共享内存
    void Creat()
    {
        umask(0);
        _shmid = shmget(_key, SIZE, IPC_CREAT | IPC_EXCL | gmode);
        if (_shmid < 0)
        {
            EXIT("shmget");
        }
        cout << "创建共享内存成功！\n";
    }

    // 获取共享内存
    void Get()
    {
        _shmid = shmget(_key, SIZE, IPC_CREAT);
        if (_shmid < 0)
        {
            EXIT("shmget");
        }
        cout << "获取共享内存成功！\n";
    }

    // 映射共享内存至虚拟空间
    void Attach()
    {
        _start_mem = shmat(_shmid, NULL, 0);
        if ((long long)_start_mem < 0)
        {
            EXIT("shmat");
        }
        cout << "映射成功！\n";
    }

    void Destroy()
    {
        UnAttach();
        int n = shmctl(_shmid, IPC_RMID, NULL);
        if (n < 0)
        {
            EXIT("shmctl");
        }
        cout << "删除共享内存成功！\n";
    }

    // 获取开始地址
    void *Start()
    {
        return _start_mem;
    }

private:
    // 解除映射
    void UnAttach()
    {
        int n = shmdt(_start_mem);
        if (n < 0)
        {
            EXIT("shmdt");
        }
        cout << "解除映射成功！\n";
    }

    key_t _key;
    int _shmid;
    void *_start_mem;
};